package com.mvc.web.common.utils;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.servlet.http.HttpServletRequest;

public class ToolsUtils {

    private static String reg_cardno_18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|X|X]{1})$";
    private static String reg_cardno_15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
    private static String reg_phone = "^(13[0-9]|14[0-9]|15[0-9]|17[0-9]|18[0-9])\\d{8}$";
    private static String reg_birth = "^[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])$";
    private static String reg_email = "^(([0-9a-zA-Z]+)|([0-9a-zA-Z]+[_.0-9a-zA-Z-]*[0-9a-zA-Z]+))@([a-zA-Z0-9-]+[.])+([a-zA-Z]{2}|net|NET|com|COM|gov|cn|CN|GOV|mil|MIL|org|ORG|edu|EDU|int|INT)$";
    private static String reg_bank = "^(\\d{5,30})$";
    private static String regEx = "[`~!#$%^&*()+=|{}':;',\\[\\]<>/?~！#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
    private static String reg_url = "^((ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&amp;%\\$#_]*))$";
    private static String reg_mobile = "^((\\d{7,8})|(\\d{4}|\\d{3})(\\d{7,8})|(\\d{4}|\\d{3})(\\d{7,8})(\\d{4}|\\d{3}|\\d{2}|\\d{1})|(\\d{7,8})(\\d{4}|\\d{3}|\\d{2}|\\d{1}))$";

    private static String reg_abc_num = "^[A-Za-z0-9]+$";
    private static String reg_CN_abc = "^[a-zA-Z\u4E00-\u9FA5]+$";
    
    public static boolean isEmpty(String strIn) {
        return strIn == null || "".equals(strIn) || "".equals(strIn.trim());
    }

    public static boolean isNotEmpty(String strIn) {
        return !isEmpty(strIn);
    }

    public static int parseInt(String str, int i) {
        if (isEmpty(str)) {
            return 0;
        } else {
            return Integer.parseInt(str);
        }
    }

    public static int getAgeFromBirthday(String str) {
        if (isEmpty(str)) {
            return 0;
        }
        try {
            int year = Integer.parseInt(str.substring(0, 4));
            int month = Integer.parseInt(str.substring(4, 6));
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            String nowTime = df.format(new Date());
            String[] nows = nowTime.split("-");

            Integer age = Integer.parseInt(nows[0]) - year;
            // 判断月份是否减一
            if (Integer.parseInt(nows[1]) - month < 0) {
                age = age - 1;
            }
            return age;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }

    /**
     * @Description: 验证身份证号
     * @author 白海安 （baihaian@126.com） 2016年6月15日 下午3:28:32
     * @version V1.0
     */
    public static boolean ValidataCardNo(String cardNo) {
        // 编译正则表达式
        Pattern p = Pattern.compile(reg_cardno_18);
        Pattern p2 = Pattern.compile(reg_cardno_15);
        Matcher m = p.matcher(cardNo);
        Matcher m2 = p2.matcher(cardNo);
        if (m.matches() || m2.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 验证手机号
     * @author 白海安 （baihaian@126.com） 2016年6月15日 下午3:28:24
     * @version V1.0
     */
    public static boolean ValidatePhone(String phone) {
        if (isEmpty(phone)) {
            return true;
        }
        Pattern p = Pattern.compile(reg_phone);
        Matcher m = p.matcher(phone);
        if (m.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 校验电话号码
     * @author 白海安 （baihaian@126.com） 2016年9月27日 下午5:24:46
     * @version V1.0
     */
    public static boolean ValidateMoblie(String moblie) {
        if (isEmpty(moblie)) {
            return true;
        }
        Pattern p = Pattern.compile(reg_mobile);
        Matcher m = p.matcher(moblie);
        if (m.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 校验出生日期
     * @author 白海安 （baihaian@126.com） 2016年6月15日 下午3:28:12
     * @version V1.0
     */
    public static boolean ValidateBirth(String phone) {
        Pattern p = Pattern.compile(reg_birth);
        Matcher m = p.matcher(phone);
        if (m.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 邮箱校验
     * @author 白海安 （baihaian@126.com） 2016年7月4日 下午7:30:14
     * @version V1.0
     */
    public static boolean ValiadteEmail(String email) {
        Pattern p = Pattern.compile(reg_email);
        Matcher m = p.matcher(email);
        if (m.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 银行卡号校验
     * @author 白海安 （baihaian@126.com） 2016年7月4日 下午7:30:57
     * @version V1.0
     */
    /*public static boolean ValiadteBankNo(String bankNo) {
        Pattern p = Pattern.compile(reg_bank);
        Matcher m = p.matcher(bankNo);
        if (m.matches()) {
            return true;
        }
        return false;
    }*/

    /**
     * @Description: 验证字符串的长度
     * @author 白海安 （baihaian@126.com） 2016年7月5日 上午10:01:03
     * @version V1.0
     */
    public static boolean ValidateStrLength(String strIn, int length) {
        if (isEmpty(strIn)) {
            return true;
        }
        if (getStrByteLen(strIn) > length) {
            return false;
        } else {
            return true;
        }
    }

    public static int getStrByteLen(String str) {
        if (null == str) {
            return 0;
        }
        char[] chars = str.toCharArray();
        int len = 0;
        for (char c : chars) {
            if (c < 256) {
                len++;
            } else {
                len += 2;
            }
        }
        return len;
    }

    public static boolean ValidateStringFilter(String str)
            throws PatternSyntaxException {
        // 清除掉所有特殊字符
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        if (m.find()) {
            return false;
        }
        return true;
    }

    public static boolean ValidateIsUrl(String str)
            throws PatternSyntaxException {
        Pattern p = Pattern.compile(reg_url);
        Matcher m = p.matcher(str);
        if (m.matches()) {
            return true;
        }
        return false;
    }

    /**
     * @Description: 时间差
     * @author 白海安 （baihaian@126.com） 2016年8月9日 下午4:39:33
     * @version V1.0
     */
    public static int getMonthSpace(String date) {
        int result = 0;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        try {
            c1.setTime(sdf.parse(date));
            c2.setTime(sdf.parse(sdf.format(new Date())));
            result = (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) * 12;
            if (c2.get(Calendar.DAY_OF_MONTH) - c1.get(Calendar.DAY_OF_MONTH) >= 0) {
                result = result + c2.get(Calendar.MONDAY) - c1.get(Calendar.MONTH);
            } else {
                result = result + c2.get(Calendar.MONDAY) - c1.get(Calendar.MONTH) - 1;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result == 0 ? 0 : Math.abs(result);
    }
    
    /** 
     * 时间戳转换成日期格式字符串 
     * @param seconds 精确到秒的字符串 
     * @param formatStr 
     * @return 
     */  
    public static String timeStamp2Date(String seconds,String format) {  
        if(seconds == null || seconds.isEmpty() || seconds.equals("null")){  
            return "";  
        }  
        if(format == null || format.isEmpty()) format = "yyyy-MM-dd HH:mm:ss";  
        SimpleDateFormat sdf = new SimpleDateFormat(format);  
        return sdf.format(new Date(Long.valueOf(seconds+"000")));  
    }  
    
    /** 
     * 日期格式字符串转换成时间戳 
     * @param date 字符串日期 
     * @param format 如：yyyy-MM-dd HH:mm:ss 
     * @return 
     */  
    public static Long date2TimeStamp(String date_str,String format){  
        try {  
            SimpleDateFormat sdf = new SimpleDateFormat(format);  
            return sdf.parse(date_str).getTime();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return 0l;  
    }  

    /**
     * @Description 上个月
     * @author 白海安 （baiha@jizhicar.com） 2017年4月1日 上午11:22:25
     * @version V1.5 
     */
    public static String getPrecedingMonth(String date) {
    	Calendar time = Calendar.getInstance();
    	time.setTimeInMillis(date2TimeStamp(date, "yyyy-MM"));
		time.add(Calendar.MONTH, -1); 
		Date afterDate = (Date) time.getTime();
		String time2 = new SimpleDateFormat("yyyy-MM").format(afterDate);
		return time2;
    }
    
    /**
     * @Description 昨天
     * @author 白海安 （baiha@jizhicar.com） 2017年4月1日 上午11:22:32
     * @version V1.5 
     */
    public static String getPrecedingDay(String date) {
    	Calendar time = Calendar.getInstance();
    	time.setTimeInMillis(date2TimeStamp(date, "yyyy-MM-dd"));
    	time.add(Calendar.DATE, -1); 
    	Date afterDate = (Date) time.getTime();
    	String time2 = new SimpleDateFormat("yyyy-MM-dd").format(afterDate);
    	return time2;
    }

    /**
     * @Description: 根据类型获取时间戳
     * @author 白海安 （baihaian@126.com） 2016年8月9日 下午4:39:18
     * @version V1.0
     */
    public static int getTime(Integer type) {
        try {
            //1今日2本周3本月4上月
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());
            String time = "0000-00-00 00:00:00";
            if (type == 1) {
                time = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());
            } else if (type == 2) {
                int week_day = cal.get(Calendar.DAY_OF_WEEK) - 1;
                if (week_day <= 0) {
                    week_day = 7;
                }
                cal.add(Calendar.DAY_OF_MONTH, -week_day + 1);
                Date afterDate = (Date) cal.getTime();
                time = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(afterDate);
            } else if (type == 3) {
                time = new SimpleDateFormat("yyyy-MM-01 00:00:00").format(new Date());
            } else if (type == 4) {
                cal.add(Calendar.MONTH, -1);
                Date afterDate = (Date) cal.getTime();
                time = new SimpleDateFormat("yyyy-MM-01 00:00:00").format(afterDate);
            }

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = format.parse(time);
            System.out.println("time===" + time);
            return (int) (date.getTime() / 1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @Description: 获取上月月份
     * @author 白海安 （baihaian@126.com） 2016年8月9日 下午4:37:02
     * @version V1.0
     */
    public static String getBeforeMonth(Integer type) {
        try {
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());
            cal.add(Calendar.MONTH, -1);
            Date afterDate = (Date) cal.getTime();
            if (type == 1) {
                String time = new SimpleDateFormat("yyyy-MM").format(afterDate);
                return time;
            } else if (type == 2) {
                String time = new SimpleDateFormat("MM").format(afterDate);
                return time;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 校验银行卡卡号
     *
     * @param cardId
     * @return
     */
    public static boolean ValiadteBankNo(String cardId) {
    	if(isEmpty(cardId)){
    		return true;
    	}
    	Pattern p = Pattern.compile(reg_bank);
        Matcher m = p.matcher(cardId);
        if (m.matches()) {
            return true;
        }
        return false;
    }
/*    public static boolean ValiadteBankNo(String cardId) {
    	if(isEmpty(cardId)){
    		return true;
    	}
    	char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1));
    	if (bit == 'N') {
    		return false;
    	}
    	return cardId.charAt(cardId.length() - 1) == bit;
    }
*/
    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     *
     * @param nonCheckCodeCardId
     * @return
     */
    public static char getBankCardCheckCode(String nonCheckCodeCardId) {
        if (nonCheckCodeCardId == null || nonCheckCodeCardId.trim().length() == 0
                || !nonCheckCodeCardId.matches("\\d+")) {
            //如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeCardId.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }

    public static String getBrowserName(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent").toLowerCase();
        String browser = "unknow";
        if (userAgent == null || "".equals(userAgent.trim())) {
            return browser;
        }
        if (userAgent.indexOf("msie") >= 0 || userAgent.indexOf("trident") >= 0) {
            browser = "IE";
            return browser;
        }
        if (userAgent.indexOf("chrome") >= 0) {
            browser = "Chrome";
            return browser;
        }
        if (userAgent.indexOf("firefox") >= 0) {
            browser = "Firefox";
            return browser;
        }
        if (userAgent.indexOf("adobeair") >= 0) {
            browser = "AdobeAIR";
            return browser;
        }
        StringTokenizer token = new StringTokenizer(userAgent, ";");
        token.nextToken();
        browser = token.nextToken();
        return browser.substring(0, browser.length() > 19 ? 19 : browser.length() - 1);
    }
    
    private static SimpleDateFormat dateFormat = null;
    static {
    	// 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        dateFormat = new SimpleDateFormat("yyyy-MM");
        // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
        dateFormat.setLenient(false);
    }
    
    public static boolean isValidDate(String s){
    	try {
			dateFormat.parse(s);
			return true;
		} catch (Exception e) {
			return false;
		}
    }
    
    public static boolean ValiadteAbc_num(String strIn) {
    	if(isEmpty(strIn)){
    		return true;
    	}
    	Pattern p = Pattern.compile(reg_abc_num);
        Matcher m = p.matcher(strIn);
        if (m.matches()) {
            return true;
        }
        return false;
    }
    
    public static boolean ValiadteCN_Abc(String strIn) {
    	if(isEmpty(strIn)){
    		return true;
    	}
    	Pattern p = Pattern.compile(reg_CN_abc);
    	Matcher m = p.matcher(strIn);
    	if (m.matches()) {
    		return true;
    	}
    	return false;
    }
    

	/**   
	* @Description: 保留两位小数
	* @author 白海安 （baihaian@126.com） 2016年9月19日 下午4:15:33
	* @version V1.0   
	*/
	public static  String TwoDecimalPlaces(Double d){
		if(d ==null){
			return "0.00";
		}
		DecimalFormat df = new DecimalFormat( "0.00");
		return df.format(d);
	}
	
	/** 
	 * @Description: 获取真实ip 
	 * @author baihaian(baiha@jizhicar.com) 2017年6月15日 上午11:53:30
	 * @param request
	 * @return
	 * @version V1.5.5
	 */
	public static String getRealIP(HttpServletRequest request){
		String remoteAddr = request.getRemoteAddr();
		String forwarded = request.getHeader("X-Forwarded-For");
		String realIp = request.getHeader("X-Real-IP");
		String ip = null;
		if (realIp == null) {
			if (forwarded == null) {
				ip = remoteAddr;
			} else {
				ip = remoteAddr + "/" + forwarded.split(",")[0];
			}
		} else {
			if (realIp.equals(forwarded)) {
				ip = realIp;
			} else {
				if (forwarded != null) {
					forwarded = forwarded.split(",")[0];
				}
				ip = realIp + "/" + forwarded;
			}
		}
		return ip;
	}

    public static void main(String[] args) {
    	System.out.println(UUID.randomUUID().toString().substring(0, 8));
    }
    
    /**
     * @Description 上个月的最后一天
     * @author cuizhenzhen(cuizz@jizhicar.com) 2017年8月17日
     * @version 2.1.2
     */
    public static String getPrecedingMonthEndday() {
    	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
		Calendar c = Calendar.getInstance();   
		c.set(Calendar.DAY_OF_MONTH, 1); 
    	c.add(Calendar.DATE, -1);
		String date  = format.format(c.getTime());  
    	return date;
    }
    /** 
     * @Description: 字母转数字 
     * @author 白海安(baiha@jizhicar.com) 2017年9月4日 上午10:40:33
     * @version V1.0
     */
    public static String letter2Num(String input) {  
        String reg = "[a-zA-Z]";  
        StringBuffer strBuf = new StringBuffer();  
        input = input.toLowerCase();  
        if (null != input && !"".equals(input)) {  
            for (char c : input.toCharArray()) {  
                if (String.valueOf(c).matches(reg)) {  
                    strBuf.append(c - 96);  
                } else {  
                    strBuf.append(c);  
                }  
            }  
            return strBuf.toString();  
        } else {  
            return input;  
        }  
    }
}
